package com.sqlcheck.service;

import com.sqlcheck.dto.response.TaskProgressInfo;
import com.sqlcheck.enums.TaskStage;
import com.sqlcheck.enums.TaskType;
import lombok.extern.slf4j.Slf4j;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 任务进度管理服务
 * 负责进度推送、里程碑管理和预估时间计算
 */
@Service
@Slf4j
public class TaskProgressService {

    // WebSocket消息模板 - 可选依赖，避免在没有WebSocket时启动失败
    @Autowired(required = false)
    private SimpMessagingTemplate messagingTemplate;

    /**
     * 任务进度缓存 - 用于计算预估时间
     */
    private final Map<Long, TaskProgressTracker> taskTrackers = new ConcurrentHashMap<>();

    /**
     * 里程碑定义
     */
    private static final Map<TaskStage, MilestoneDefinition> MILESTONES = new HashMap<>();

    static {
        // 定义各阶段的里程碑信息
        MILESTONES.put(TaskStage.GIT_CLONE_COMPLETE, new MilestoneDefinition(
                "代码下载完成",
                "成功从Git仓库下载源码，准备进行代码扫描",
                "🎯"));

        MILESTONES.put(TaskStage.SQL_EXTRACTION_COMPLETE, new MilestoneDefinition(
                "SQL提取完成",
                "成功从源码中提取SQL语句，发现{sqlCount}条SQL语句",
                "📊"));

        MILESTONES.put(TaskStage.RULE_ANALYSIS_COMPLETE, new MilestoneDefinition(
                "规则分析完成",
                "完成兼容性规则分析，发现{issueCount}个潜在问题",
                "🔍"));

        MILESTONES.put(TaskStage.AI_VERIFICATION_COMPLETE, new MilestoneDefinition(
                "AI验证完成",
                "AI增强验证完成，确认{confirmedCount}个问题",
                "🤖"));

        MILESTONES.put(TaskStage.COMPLETION, new MilestoneDefinition(
                "分析任务完成",
                "所有分析工作完成，生成完整的兼容性分析报告",
                "✅"));
    }

    /**
     * 更新任务进度
     */
    public void updateProgress(Long taskId, TaskStage stage, int progress, String message) {
        TaskProgressTracker tracker = getOrCreateTracker(taskId);
        tracker.updateProgress(stage, progress, message);

        TaskProgressInfo progressInfo = TaskProgressInfo.progress(taskId, stage, progress, message);
        // 移除不准确的时间预估
        // progressInfo.setEstimatedRemainingSeconds(tracker.getEstimatedRemainingSeconds());

        pushProgress(progressInfo);
    }

    /**
     * 更新任务进度（带统计信息）
     */
    public void updateProgress(Long taskId, TaskStage stage, int progress, String message,
            Map<String, Object> statistics) {
        TaskProgressTracker tracker = getOrCreateTracker(taskId);
        tracker.updateProgress(stage, progress, message);

        TaskProgressInfo progressInfo = TaskProgressInfo.progress(taskId, stage, progress, message);
        progressInfo.setStatistics(statistics);
        // 移除不准确的时间预估
        // progressInfo.setEstimatedRemainingSeconds(tracker.getEstimatedRemainingSeconds());

        pushProgress(progressInfo);
    }

    /**
     * 报告里程碑完成
     */
    public void reportMilestone(Long taskId, TaskStage stage, Map<String, Object> statistics) {
        MilestoneDefinition milestone = MILESTONES.get(stage);
        if (milestone == null) {
            log.debug("Stage {} 不是里程碑节点", stage);
            return;
        }

        TaskProgressTracker tracker = getOrCreateTracker(taskId);
        tracker.completeMilestone(stage);

        // 格式化里程碑描述
        String description = formatMilestoneDescription(milestone.description, statistics);
        String title = milestone.icon + " " + milestone.title;

        TaskProgressInfo milestoneInfo = TaskProgressInfo.milestone(
                taskId, stage, title, description, statistics);
        milestoneInfo.setCompletedMilestones(tracker.getCompletedMilestones());
        // 移除不准确的时间预估
        // milestoneInfo.setEstimatedRemainingSeconds(tracker.getEstimatedRemainingSeconds());

        log.info("里程碑达成: taskId={}, stage={}, title={}", taskId, stage, title);
        pushProgress(milestoneInfo);
    }

    /**
     * 批量进度更新（用于分批处理）
     */
    public ProgressCallback createProgressCallback(Long taskId, TaskStage stage,
            String operationName, int baseProgress, int progressRange) {
        return new ProgressCallback() {
            @Override
            public void onProgress(int current, int total, String message) {
                int currentProgress = baseProgress + (int) ((double) current / total * progressRange);
                // 不重复显示进度计数，让具体的message自己处理格式化
                String formattedMessage = String.format("[%s] %s", operationName, message);
                updateProgress(taskId, stage, currentProgress, formattedMessage);
            }

            @Override
            public void onStageProgress(String stageName, int progress, String message) {
                updateProgress(taskId, stage, progress, String.format("[%s] %s", stageName, message));
            }
        };
    }

    /**
     * 任务开始
     */
    public void startTask(Long taskId, TaskType taskType) {
        TaskProgressTracker tracker = new TaskProgressTracker(taskId, taskType);
        taskTrackers.put(taskId, tracker);

        updateProgress(taskId, TaskStage.INITIALIZATION, 0, "任务开始执行...");
    }

    /**
     * 任务完成
     */
    public void completeTask(Long taskId, Map<String, Object> finalStatistics) {
        reportMilestone(taskId, TaskStage.COMPLETION, finalStatistics);

        // 清理跟踪器（延迟清理，保留1小时）
        Timer timer = new Timer(true);
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                taskTrackers.remove(taskId);
            }
        }, 3600_000); // 1小时后清理
    }

    /**
     * 推送进度信息
     */
    private void pushProgress(TaskProgressInfo progressInfo) {
        // 记录进度日志
        String logMessage = String.format("任务进度更新: taskId=%d, progress=%d%%, stage=%s, message=%s",
                progressInfo.getTaskId(), progressInfo.getProgress(),
                progressInfo.getCurrentStage(), progressInfo.getMessage());

        if (Boolean.TRUE.equals(progressInfo.getIsMilestone())) {
            log.info("🎯 里程碑: {}", logMessage);
        } else {
            log.info("📈 进度: {}", logMessage);
        }

        // 推送到前端 - 任务特定频道
        try {
            if (messagingTemplate != null) {
                messagingTemplate.convertAndSend(
                        "/topic/task/" + progressInfo.getTaskId() + "/progress",
                        progressInfo);

                // 同时推送到通用进度频道（可选，用于管理员监控）
                messagingTemplate.convertAndSend("/topic/progress", progressInfo);

                log.debug("WebSocket进度推送成功: taskId={}", progressInfo.getTaskId());
            } else {
                log.debug("WebSocket未配置，跳过进度推送: taskId={}", progressInfo.getTaskId());
            }
        } catch (Exception e) {
            log.warn("WebSocket进度推送失败: taskId={}, error={}",
                    progressInfo.getTaskId(), e.getMessage());
        }
    }

    /**
     * 获取或创建任务跟踪器
     */
    private TaskProgressTracker getOrCreateTracker(Long taskId) {
        return taskTrackers.computeIfAbsent(taskId, id -> new TaskProgressTracker(id, null));
    }

    /**
     * 格式化里程碑描述
     */
    private String formatMilestoneDescription(String template, Map<String, Object> statistics) {
        if (statistics == null)
            return template;

        String result = template;
        for (Map.Entry<String, Object> entry : statistics.entrySet()) {
            String placeholder = "{" + entry.getKey() + "}";
            if (result.contains(placeholder)) {
                result = result.replace(placeholder, String.valueOf(entry.getValue()));
            }
        }
        return result;
    }

    /**
     * 里程碑定义
     */
    private static class MilestoneDefinition {
        final String title;
        final String description;
        final String icon;

        MilestoneDefinition(String title, String description, String icon) {
            this.title = title;
            this.description = description;
            this.icon = icon;
        }
    }

    /**
     * 任务进度跟踪器
     */
    private static class TaskProgressTracker {
        private final Long taskId;
        private final TaskType taskType;
        private final long startTime;
        private final List<TaskProgressInfo.MilestoneInfo> completedMilestones = new ArrayList<>();

        private TaskStage currentStage;
        private int currentProgress;
        private long lastUpdateTime;

        public TaskProgressTracker(Long taskId, TaskType taskType) {
            this.taskId = taskId;
            this.taskType = taskType;
            this.startTime = System.currentTimeMillis();
            this.lastUpdateTime = startTime;
        }

        public void updateProgress(TaskStage stage, int progress, String message) {
            this.currentStage = stage;
            this.currentProgress = progress;
            this.lastUpdateTime = System.currentTimeMillis();
        }

        public void completeMilestone(TaskStage stage) {
            TaskProgressInfo.MilestoneInfo milestone = TaskProgressInfo.MilestoneInfo.builder()
                    .stage(stage)
                    .title(MILESTONES.get(stage).title)
                    .completedAt(System.currentTimeMillis())
                    .progress(stage.getEndProgress())
                    .build();

            completedMilestones.add(milestone);
        }

        public List<TaskProgressInfo.MilestoneInfo> getCompletedMilestones() {
            return new ArrayList<>(completedMilestones);
        }

        public Long getEstimatedRemainingSeconds() {
            if (currentProgress <= 0)
                return null;

            long elapsedMs = System.currentTimeMillis() - startTime;
            long estimatedTotalMs = (long) (elapsedMs * 100.0 / currentProgress);
            long remainingMs = estimatedTotalMs - elapsedMs;

            return Math.max(0, remainingMs / 1000);
        }
    }
}